
/**
 * AppleIIGo
 * CPU class
 * (C) 2008 by Marc S. Ressl (mressl@umich.edu)
 * Released under the GPL
 */

#include "CPU.h"
#include "MOS6502.h"
#include "W65C02S.h"
#include "W65C816S.h"
#include "Z80.h"

class CPU * CPU::getInstance(UINT32 cpuType, class Motherboard * motherboard) {
	switch(cpuType) {
		case CPUTYPE_MOS6502:
			return new W65C02S(motherboard);
		case CPUTYPE_W65C02S:
			return new W65C02S(motherboard);
		case CPUTYPE_W65C816S:
			return 0;
		case CPUTYPE_Z80:
			return 0;
		default:
			return 0;
	}
}

CPU::CPU(class Motherboard * motherboard, char * deviceName) :
Device(motherboard, deviceName) {
	cycleIndex = 0;
	cycleNum = 1;
	
	irqAssertedCount = 0;
	resetAssertedCount = 0;
	isReset = 0;
	isRestart = 0;
	isNmi = 0;
	isWait = 0;
	isStop = 0;
}

void CPU::onDevicesConnected() {
	this->mmu = motherboard->getMmu();
}

void CPU::assertIrq() {
	irqAssertedCount++;
}

void CPU::clearIrq() {
	irqAssertedCount--;
}

bool CPU::isIrqAsserted() {
	return irqAssertedCount;
}

void CPU::triggerNmi() {
	isNmi = true;
}

void CPU::assertReset(bool isRestart) {
	this->isRestart = isRestart;
	isStop = true;
	if (!resetAssertedCount)
		motherboard->onResetAsserted(isRestart);
	resetAssertedCount++;
}

void CPU::clearReset() {
	resetAssertedCount--;
	if (!resetAssertedCount) {
		isReset = true;
		isWait = false;
		isStop = false;
		motherboard->onResetCleared();
	}
}

bool CPU::isResetAsserted() {
	return resetAssertedCount;
}

void CPU::setCycleIndex(UINT32 value) {
	cycleIndex = value;
}

UINT32 CPU::getCycleIndex() {
	return cycleIndex;
}

void CPU::setCycleNum(UINT32 value) {
	cycleNum = value;
}

UINT32 CPU::getCycleNum() {
	return cycleNum;
}

void CPU::executeInstructions() {
	cycleIndex = 0;
}
